//////////////////////////////////////////////////////////////////////////
// 
// Copyright
// Author
// 
// 
//////////////////////////////////////////////////////////////////////////


#pragma once
#include "GSE_Log.h"


namespace GSE
{
	class CLogSinkNull : public ILogSink
	{
	public:
		static CLogSinkNull* Instance()  { static CLogSinkNull sink; return &sink; }

		virtual void Write(int)	{}
		virtual void Flush() {}
		virtual const char * SinkName()
		{
			return "NullSink";
		}

		virtual void SetSinkParam(const char * ) {}
		virtual void SetSinkParam(const wchar_t * ) {}

	private:
		CLogSinkNull() {}
		virtual ~CLogSinkNull(){}
	};


	template<class T, class Tr = std::char_traits<T>, class A = std::allocator<T> >
	class CDebugStringBuf : public std::basic_stringbuf<T, Tr, A>
	{
	private:
#ifndef WIN32
		typedef Tr traits_type;
#endif
	public:
		CDebugStringBuf(ILogSink* ps = CLogSinkNull::Instance()) : m_poSink(ps) {}
		~CDebugStringBuf() { m_poSink->Flush();}

		typedef typename std::basic_stringbuf<T, Tr, A>::int_type int_type;

		int_type overflow (int_type c)
		{
			if (c != traits_type::eof())
			{
				m_poSink->Write (c);
			}
			return traits_type::not_eof(c);
		}

		void SetSink(ILogSink* ps) { m_poSink = ps;}
		const ILogSink* GetSink()	{ return m_poSink; }

	private:
		CDebugStringBuf(const CDebugStringBuf&);
		CDebugStringBuf& operator=(const CDebugStringBuf&);
		ILogSink* m_poSink;       ///< current sink
	};

	class CLogSystem : public ILogSystem
	{
	public:
		CLogSystem();
		virtual ~CLogSystem();

		CDebugStringBuf<wchar_t>* GetDebugStream()	{ return &m_oDebugStream; }

		virtual void SetSink(const char * strSinkName);
		virtual void RegisterSink(ILogSink * lpSink);
		virtual ILogSink * UnRegisterSink(const char * strSinkName);
		virtual ILogSink * GetSink(const char * strSinkName);
		virtual void Write(const char * lpStr);
		virtual void Write(const wchar_t * lpStr);

		virtual void PrintFile(bool value);
		virtual void PrintLine(bool value);
		virtual void PrintTime(bool value);

		virtual bool IsPrintFile();
		virtual bool IsPrintLine();
		virtual bool IsPrintTime();

		virtual void OpenLevel(LogLevel eLevel,bool bOpen);
		virtual bool IsOpenLevel(LogLevel eLevel);

	private:
		CDebugStringBuf<wchar_t>			m_oDebugStream;       ///< the debug_stream
		std::map<std::string,ILogSink *>	m_RegisterSinks;
		std::wostream						m_cout;

		bool								m_bPrintFile;
		bool								m_bPrintLine;
		bool								m_bPrintTime;
		std::map<int,bool>					m_mapLevels;
	public:
		static CLogSystem *					m_pInstance;
	};
}